package com.github.aloxc.plugin.restplus.navigation.action;

import com.github.aloxc.plugin.restplus.common.Consts;
import com.github.aloxc.plugin.restplus.method.HttpMethod;
import com.github.aloxc.plugin.restplus.method.action.ModuleHelper;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.module.Module;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.psi.KtClass;
import org.jetbrains.kotlin.psi.KtNamedFunction;

import javax.swing.*;


/**
 * RequestMappingNavigationItem
 * @author leero
 */
public class RestServiceItem implements NavigationItem, Comparable<RestServiceItem> {
    private PsiClass psiClass;
    private PsiMethod psiMethod;
    private PsiElement psiElement;
    private Module module;
    private HttpMethod method;
    private String url;
    private boolean foundRequestBody;
    private Navigatable navigationElement;
    private boolean swagger;
    private String parentName;
    private String description;


    public RestServiceItem(PsiClass psiClass,PsiElement psiElement, String requestMethod, String urlPath, boolean foundRequestBody,String description) {
        this.foundRequestBody = foundRequestBody;
        this.psiClass = psiClass;
        this.psiElement = psiElement;
        if (psiElement instanceof PsiMethod) {
            this.psiMethod = (PsiMethod) psiElement;
        }
        if (requestMethod != null) {
            method = HttpMethod.getByRequestMethod(requestMethod);
        }

        this.url = urlPath;
        if (psiElement instanceof Navigatable) {
            navigationElement = (Navigatable) psiElement;
        }
        this.description = description;
    }
    public boolean isFoundRequestBody() {
        return foundRequestBody;
    }

    public String getParentName() {
        return parentName;
    }

    public PsiClass getPsiClass() {
        return psiClass;
    }

    public void setPsiClass(PsiClass psiClass) {
        this.psiClass = psiClass;
    }

    public void setParentName(String parentName) {
        this.parentName = parentName;
    }

    public void setFoundRequestBody(boolean foundRequestBody) {
        this.foundRequestBody = foundRequestBody;
    }

    public boolean isSwagger() {
        return swagger;
    }

    public void setSwagger(boolean swagger) {
        this.swagger = swagger;
    }

    @Nullable
    @Override
    public String getName() {
        return this.url;
    }

    @Nullable
    @Override
    public ItemPresentation getPresentation() {
        return new RestServiceItemPresentation();
    }

    @Override
    public void navigate(boolean requestFocus) {
        if (navigationElement != null) {
            navigationElement.navigate(requestFocus);
        }
    }

    @Override
    public boolean canNavigate() {
        return navigationElement.canNavigate();
    }

    @Override
    public boolean canNavigateToSource() {
        return true;
    }


    /**
     * 匹配
     */
    public boolean matches(String queryText) {
        String pattern = queryText;
        if ("/".equals(pattern)) {
            return true;
        }

        com.intellij.psi.codeStyle.MinusculeMatcher matcher = com.intellij.psi.codeStyle.NameUtil.buildMatcher("*" + pattern, com.intellij.psi.codeStyle.NameUtil.MatchingCaseSensitivity.NONE);
        return matcher.matches(this.url);
    }

    @Override
    public int compareTo(@NotNull RestServiceItem o) {
        return this.getUrl().compareTo(o.getUrl());
    }

    private class RestServiceItemPresentation implements ItemPresentation {
        @Nullable
        @Override
        public String getPresentableText() {
//            return requestMethod  + " " + url;
            return url;
        }

        //        对应的文件位置显示
        @Nullable
        @Override
        public String getLocationString() {
            if(!isSwagger()) {
                String fileName = psiElement.getContainingFile().getName();

                String location = null;

                if (psiElement instanceof PsiMethod) {
                    PsiMethod psiMethod = ((PsiMethod) psiElement);
                    location = module.getName().concat(" -> ").concat(psiMethod.getContainingClass().getName().concat("#")).concat(psiMethod.getName());
                } else if (psiElement instanceof KtNamedFunction) {
                    KtNamedFunction ktNamedFunction = (KtNamedFunction) RestServiceItem.this.psiElement;
                    String className = ((KtClass) psiElement.getParent().getParent()).getName();
                    location = module.getName().concat(" -> ").concat(className.concat("#")).concat(ktNamedFunction.getName());
                }

                return "(" + location + ")";
            }else{
                String location = parentName +  " ->" + RestServiceItem.this.getUrl();
                return "(" + location + ")";
            }
        }

        @Nullable
        @Override
        public Icon getIcon(boolean unused) {
            return Consts.Method.get(method, foundRequestBody);
        }
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Module getModule() {
        return module;
    }

    public PsiMethod getPsiMethod() {
        return psiMethod;
    }

    public void setPsiMethod(PsiMethod psiMethod) {
        this.psiMethod = psiMethod;
    }

    public HttpMethod getMethod() {
        if (method == null) {
            return HttpMethod.GET;
        }
        return method;
    }

    public void setMethod(HttpMethod method) {
        this.method = method;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getFullUrl() {
        if (module == null) {
            return getUrl();
        }

        ModuleHelper moduleHelper = ModuleHelper.create(module);
        // 处理 Mapping 设置个 value
        return moduleHelper.getServiceHostPrefix() + getUrl();
    }


    public void setModule(Module module) {
        this.module = module;
    }

    public PsiElement getPsiElement() {
        return psiElement;
    }


}
